﻿module IronLua.Runtime.DynamicLanguageRuntime

open IronLua
open System.Linq.Expressions
open System.Dynamic

let rec empty = Expression.Empty
and lambda<'a> body (name : string) parms = Expression.Lambda<'a>(body, name, parms)    
and param (name : string) (t : System.Type) = Expression.Parameter(t, name)
and body (stmts : Expression seq) = Expression.Block(stmts)
and trycatchfinally body catch finally' = 
    Expression.TryCatchFinally(body, finally', catch)
and block (stmts : Expression seq) = Expression.Block stmts
and blockstmt (stmt : Expression) = Expression.Block [ stmt ]
and catch (ex : ParameterExpression) block = Expression.Catch(ex, block) 
and luacatchall luaresult = [|
        catch (param "ex" typeof<LuaSyntaxException>) (blockstmt(Expression.Assign(luaresult, Expression.Constant(LuaResult.SyntaxError))));
        catch (param "ex" typeof<LuaRuntimeException>) (blockstmt(Expression.Assign(luaresult, Expression.Constant(LuaResult.RuntimeError))));
        catch (param "ex" typeof<LuaMemoryException>) (blockstmt(Expression.Assign(luaresult, Expression.Constant(LuaResult.MemoryError))));
        catch (param "ex" typeof<LuaException>) (blockstmt(Expression.Assign(luaresult, Expression.Constant(LuaResult.RuntimeError))));
    |]

and luaSetThreadState luathread luaresult = 
    Expression.Assign(Expression.MakeMemberAccess(luathread, luaThreadResultMemberInfo), luaresult)
    
and luaThreadResultMemberInfo : System.Reflection.FieldInfo = 
    typeof<Thread>.GetField("status", System.Reflection.BindingFlags.NonPublic ||| System.Reflection.BindingFlags.Instance);
   
and luafinally luathread luaresult =     
    block([Expression.IfThen(Expression.NotEqual(luaresult, Expression.Constant(LuaResult.OK)), (luaSetThreadState luathread luaresult))])

(*
type LuaMetaObject() = inherit DynamicMetaObject()

type LuaGetMemberBinder() = inherit DynamicMetaObjectBinder()

type LuaSetMemberBinder() = inherit DynamicMetaObjectBinder()

type LuaInvokeBinder() = inherit DynamicMetaObjectBinder()

type LuaInvokeMemberBinder() = inherit DynamicMetaObjectBinder()

type LuaBinaryOperationBinder() = inherit DynamicMetaObjectBinder()

type LuaUnaryOperationBinder() = inherit DynamicMetaObjectBinder()

type LuaGetIndexBinder() = inherit DynamicMetaObjectBinder()

type LuaSetIndexBinder() = inherit DynamicMetaObjectBinder()

type LuaConvertBinder() = inherit DynamicMetaObjectBinder()
*)